package com.dingup.provider.service.sys.impl;

import com.dingup.api.model.sys.SysDept;
import com.dingup.api.model.sys.SysRole;
import com.dingup.provider.mapper.SysDeptMapper;
import com.dingup.provider.service.sys.SysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by wancheng on 2018/7/24.
 */
@Service
public class SysDeptServiceImpl implements SysDeptService {

    private List<SysDept> tree = null;

    @Autowired
    SysDeptMapper sysDeptMapper;

    @Override
    public List<SysDept> getDeptTree() {
        tree = sysDeptMapper.getAll();
        return tree;
    }

    @Override
    public List<SysDept> get(Long rootId) {
        if (tree == null) {
            getDeptTree();
        }
        return constructTaskDTOToTree(tree, rootId);
    }

    @Override
    public void clear() {
        tree = null;
    }

    @Override
    public List<SysDept> getByUser(String userId) {
        return sysDeptMapper.getDeptByUserId(userId);
    }

    @Override
    public List<Long> getChildDeptIds(Long rootId) {
        List<Long> deptIds = new ArrayList<>();
        String id = sysDeptMapper.getChildDeptIds(rootId);
        if(!StringUtils.isEmpty(id) && !StringUtils.isEmpty(id)){
            Arrays.asList(id.split(",")).stream().forEach(
                    d -> {
                        deptIds.add(Long.valueOf(d));

                    }
            );
        }
        return deptIds;
    }

    @Override
    public List<SysDept> getMyDepts(List<Long> myDeptIds) {
        List<SysDept> all = getDeptTree();
        List<SysDept> myDepts = new ArrayList<>();
        Map<Long,SysDept> allMap = all.stream().collect(Collectors.toMap(SysDept::getId,d->d));
        Set<Long> parentIds = new HashSet<>();
        myDeptIds.stream().forEach(
                id->{
                    Set<Long> p = getParents(allMap,id);
                    if (!CollectionUtils.isEmpty(p)){
                        parentIds.addAll(p);
                    }
                }
        );
        parentIds.stream().forEach(
                id->{
                    myDepts.add(allMap.get(id));
                }
        );
        List<SysDept> myDeptTree = constructTaskDTOToTree(myDepts,0L);
        return myDeptTree;
    }
    private Set<Long> getParents(Map<Long,SysDept> allDepts,Long deptId){
        Set<Long> parentIds = new HashSet<>();
        SysDept dept = allDepts.get(deptId);
        if (dept != null){
            parentIds.add(deptId);
            parentIds.addAll(getParents(allDepts,dept.getParentId()));
        }
        return parentIds;
    }

    public List<SysDept> constructTaskDTOToTree(List<SysDept> taskDTOList, Long parentId) {
        //key:父节点ID value:子节点集合
        Map<Long, List<SysDept>> taskDTOMap = new HashMap<>();

        //将List重组到Map中
        taskDTOList.forEach(dto -> {
            List<SysDept> tempTaskDTOList = taskDTOMap.get(dto.getParentId());
            if (tempTaskDTOList == null) {
                tempTaskDTOList = new ArrayList<SysDept>();
                taskDTOMap.put(dto.getParentId(), tempTaskDTOList);
            }
            tempTaskDTOList.add(dto);
        });

        //顶级节点集合
        List<SysDept> resultTaskDTOList = taskDTOMap.get(parentId);

        recurTaskDTOList(resultTaskDTOList, taskDTOMap);

        //resultTaskDTOList.stream()
        return resultTaskDTOList;
    }

    /**
     * 将重组好的Map进行树形结构处理
     *
     * @param taskDTOList 父节点集合(不一定是顶级节点 因为会递归调用)
     * @param sourceMap   组装好的Map集合
     */
    public void recurTaskDTOList(List<SysDept> taskDTOList, Map<Long, List<SysDept>> sourceMap) {
        if (CollectionUtils.isEmpty(taskDTOList))
            return;
        taskDTOList.forEach(dto -> {
            dto.setChild(sourceMap.get(dto.getId()));
            recurTaskDTOList(dto.getChild(), sourceMap);
        });
    }
}
